﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using BluetoothClientWP8.Resources;
using Windows.Networking.Sockets;
using Windows.Networking.Proximity;
using System.Diagnostics;
using Windows.Storage.Streams;
using System.Threading.Tasks;
using BluetoothConnectionManager;
using System.Windows.Media;
using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework;
using Windows.Foundation;
using Windows.Phone.Speech.Recognition;
using Windows.Phone.Speech.Synthesis;
using System.Windows.Controls.Primitives;


namespace BluetoothClientWP8
{
    public partial class MainPage : PhoneApplicationPage
    {
        private ConnectionManager connectionManager;
        Accelerometer accelerometer;
        private StateManager stateManager;
        bool[] chk = new bool[10];
        bool ghiam = false, touch = true;
        //
        SpeechSynthesizer _synthesizer;                             // The speech synthesizer (text-to-speech, TTS) object
        SpeechRecognizer _recognizer;                               // The speech recognition object
        IAsyncOperation<SpeechRecognitionResult> _recoOperation;    // Used to canel the current asynchronous speech recognition operation

        bool _recoEnabled = false;                                  // When this is true, we will continue to recognize 
        //Dictionary<string, SolidColorBrush> _colorBrushes;
        Dictionary<string, string> dict = new Dictionary<string, string>();

        //
        public MainPage()
        {
            InitializeComponent();
            if (!Accelerometer.IsSupported)
            {
                MessageBox.Show("No suppor Accelerometer!");
            }
            for(int i =0; i<6; i++) chk[i]=true; 
            connectionManager = new ConnectionManager();
            connectionManager.MessageReceived += connectionManager_MessageReceived;
            stateManager = new StateManager();
            needforspeed.Visibility = System.Windows.Visibility.Collapsed;
        }

        public void connectionManager_MessageReceived(string message)
        {
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //if(dict==null)
            {
                dict = new Dictionary<string, string>();
                dict.Add("lead on", "w");
                dict.Add("stop", "p");
                dict.Add("turn right", "e");
                dict.Add("turn left", "q");
                dict.Add("go back", "s");
                dict.Add("right back", "c");
                dict.Add("left back", "z");
                dict.Add("go ahead", "w");
                dict.Add("trái", "q");
                dict.Add("phải", "e");
                dict.Add("trước", "w");
                dict.Add("lùi", "s");
            }
            try
            {
                // Create the speech recognizer and speech synthesizer objects. 
                if (_synthesizer == null)
                {
                    _synthesizer = new SpeechSynthesizer();
                }
                if (_recognizer == null)
                {
                    _recognizer = new SpeechRecognizer();

                    // Set up a list of colors to recognize.
                    _recognizer.Grammars.AddGrammarFromList("Colors", dict.Keys);
                }

            }

            catch (Exception err)
            {
                txtResult.Text = err.ToString();
            }
            //
            connectionManager.Initialize();
            stateManager.Initialize();
            
            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            connectionManager.Terminate();
        }

        private void ConnectAppToDeviceButton_Click_1(object sender, RoutedEventArgs e)
        {
            AppToDevice();
        }

        private async void AppToDevice()
        {
            ConnectAppToDeviceButton.Content = "Connecting...";
            PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
            var pairedDevices = await PeerFinder.FindAllPeersAsync();

            if (pairedDevices.Count == 0)
            {
                Debug.WriteLine("No paired devices were found.");
            }
            else
            { 
                foreach (var pairedDevice in pairedDevices)
                {
                    if (pairedDevice.DisplayName == DeviceName.Text)
                    {
                        connectionManager.Connect(pairedDevice.HostName);
                        ConnectAppToDeviceButton.Content = "Connected";
                        BodyDetectionStatus.Text = "Detected with: "+DeviceName.Text.ToString();
                        DeviceName.IsReadOnly = true;
                        ConnectAppToDeviceButton.IsEnabled = false;
                        continue;
                    }
                }
            }
        }

        private async void goAhead_btn_Click(object sender, RoutedEventArgs e)
        {
         
             string command = "w";
             await connectionManager.SendCommand(command);
        }

        private async void turnLeft_btn_Click(object sender, RoutedEventArgs e)
        {
            string command = "q";
            await connectionManager.SendCommand(command);
        }

        private async void turnRight_btn_Click(object sender, RoutedEventArgs e)
        {
            string command = "e";
            await connectionManager.SendCommand(command);
        }

        private async void leftBack_btn_Click(object sender, RoutedEventArgs e)
        {
            string command = "z";
            await connectionManager.SendCommand(command);
        }

        private async void goBack_btn_Click(object sender, RoutedEventArgs e)
        {
            string command = "s";
            await connectionManager.SendCommand(command);
        }

        private async void rightback_btn_Click(object sender, RoutedEventArgs e)
        {
            string command = "c";
            await connectionManager.SendCommand(command);
        }
        private async void stop_btn_Click(object sender, RoutedEventArgs e)
        {
            string command = "p";
            await connectionManager.SendCommand(command);
        }

        private void Acc_cb_Checked(object sender, RoutedEventArgs e)
        {
            if (Convert.ToBoolean(Acc_cb.IsChecked))
            {
                if (accelerometer == null)
                {
                    accelerometer = new Accelerometer();
                    accelerometer.TimeBetweenUpdates = TimeSpan.FromMilliseconds(500);
                    accelerometer.CurrentValueChanged +=
                    new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelerometer_CurrentValueChanged);
                }

                try
                {
                    MessageBox.Show("Starting accelerometer.");
                    accelerometer.Start();
                }
                catch
                {
                    MessageBox.Show("Unable to start accelerometer.");
                }
            }
        }

        private void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
        {
            Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));
        }

        private void UpdateUI(AccelerometerReading accelerometerReading)
        {
            Vector3 acceleration = accelerometerReading.Acceleration;
            //DeviceName.Text = acceleration.X.ToString() + "||" + acceleration.Y.ToString();
            if (chk[0] && acceleration.Y > 0.25 && (acceleration.X > -0.2 && acceleration.X < 0.2))
            {
                for (int i = 0; i < 7; i++) chk[i] = true;
                chk[0] = false;
                goahead();
            }
            if (chk[1] && acceleration.Y < -0.25 && (acceleration.X > -0.2 && acceleration.X < 0.2))
            {
                for (int i = 0; i < 7; i++) chk[i] = true;
                chk[1] = false;
                goback();
            }

            if (chk[2] && acceleration.Y > 0.25 && (acceleration.X < -0.3))
            {
                for (int i = 0; i < 7; i++) chk[i] = true;
                chk[2] = false;
                aheadleft();
            }
            if (chk[3] && acceleration.Y > 0.25 && (acceleration.X > 0.3))
            {
                for (int i = 0; i < 7; i++) chk[i] = true;
                chk[3] = false;
                aheadright();
            }
            if (chk[4] && acceleration.Y < -0.25 && (acceleration.X < -0.3))
            {
                for (int i = 0; i < 7; i++) chk[i] = true;
                chk[4] = false;
                gobackleft();
            }
            if (chk[5] && acceleration.Y < -0.25 && (acceleration.X > 0.3))
            {
                for (int i = 0; i < 7; i++) chk[i] = true;
                chk[5] = false;
                gobackright();
            }
            if (chk[6] && acceleration.Y < 0.25 && acceleration.Y > -0.25 && (acceleration.X > -0.2 && acceleration.X < 0.2))
            {
                for (int i = 0; i < 7; i++) chk[i] = true;
                chk[6] = false;
                stop();
            }
        }

        private async void stop()
        {
            string command = "p";
            await connectionManager.SendCommand(command);
        }

        private async void gobackright()
        {
            string command = "c";
            await connectionManager.SendCommand(command);
        }

        private async void gobackleft()
        {
            string command = "z";
            await connectionManager.SendCommand(command);
        }

        private async void aheadright()
        {
            string command = "e";
            await connectionManager.SendCommand(command);
        }

        private async void aheadleft()
        {
            string command = "q";
            await connectionManager.SendCommand(command);
        }

        private async void goback()
        {
            string command = "s";
            await connectionManager.SendCommand(command);
        }

        private async void goahead()
        {
            string command = "w";
            await connectionManager.SendCommand(command);
        }



        private void Acc_cb_Unchecked(object sender, RoutedEventArgs e)
        {
            if (accelerometer != null)
            {
                accelerometer.Stop();
                MessageBox.Show("Accelerometer stopped!");
            }
        }
        //đoạn code tự chế
        private async void btnContinuousRecognition_Click(object sender, RoutedEventArgs e)
        {
            string amthanh, command;
            txtResult.Visibility = System.Windows.Visibility.Visible;
            // Change the button text. 
            ghiam = !ghiam;
            if(ghiam==false)
            {
                txtResult.Visibility = System.Windows.Visibility.Collapsed;
                _recoEnabled = false;
                ImageBrush background = new ImageBrush();
                background.ImageSource = new System.Windows.Media.Imaging.BitmapImage(new Uri(@"/Assets/Narrow/microphone.png", UriKind.Relative));
                btnContinuousRecognition.Background = background;
                return;
            }
            else
            {
                if (this._recoEnabled)
                {
                    
                    // Update the UI to the initial state
                    _recoEnabled = false;
                    //btnContinuousRecognition.Content = "Start speech recognition";
                    txtResult.Text = String.Empty;
                    //txtInstructions.Visibility = System.Windows.Visibility.Collapsed;

                    // Cancel the outstanding recognition operation, if one exists
                    if (_recoOperation != null && _recoOperation.Status == AsyncStatus.Started)
                    {
                        _recoOperation.Cancel();
                    }
                    return;
                }
                else
                {
                    //image button
                    ImageBrush background = new ImageBrush();
                    background.ImageSource = new System.Windows.Media.Imaging.BitmapImage(new Uri(@"/Assets/Narrow/recoding2.png", UriKind.Relative));
                    btnContinuousRecognition.Background = background;
                    //
                    // Set the flag to say that we are in recognition mode
                    _recoEnabled = true;

                    // Update the UI
                    //btnContinuousRecognition.Content = "Listening... tap to cancel";
                    //txtInstructions.Visibility = System.Windows.Visibility.Visible;
                }

                // Continuously recognize speech until the user has canceled 
                while (this._recoEnabled)
                {
                    try
                    {
                        // Perform speech recognition.  
                        _recoOperation = _recognizer.RecognizeAsync();
                        var recoResult = await this._recoOperation;

                        // Check the confidence level of the speech recognition attempt.
                        if (recoResult.TextConfidence < SpeechRecognitionConfidence.Medium)
                        {
                            // If the confidence level of the speech recognition attempt is low, 
                            // ask the user to try again.
                            txtResult.Text = "Not sure what you said, please try again.";
                            await _synthesizer.SpeakTextAsync("Not sure what you said, please try again");
                        }
                        else
                        {
                            // Output that the color of the rectangle is changing by updating
                            // the TextBox control and by using text-to-speech (TTS). 
                            txtResult.Text = "Changing Navigation to: " + recoResult.Text;
                            //await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);//làm xong phải bỏ lại

                            // Set the fill color of the rectangle to the recognized color. 
                            //rectangleResult.Background = TryGetBrush(recoResult.Text.ToLower());
                            //đoạn code xử lý kết quả thu âm sẽ nằm tại đây
                            amthanh = TryGetNavigation(recoResult.Text.ToLower());

                            switch (amthanh)
                            {
                                case "p":
                                    command = "p";
                                    await connectionManager.SendCommand(command);
                                    await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);
                                    break;
                                case "e":
                                    command = "e";
                                    await connectionManager.SendCommand(command);
                                    await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);
                                    break;
                                case "q":
                                    command = "q";
                                    await connectionManager.SendCommand(command);
                                    await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);
                                    break;
                                case "s":
                                    command = "s";
                                    await connectionManager.SendCommand(command);
                                    await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);
                                    break;
                                case "c":
                                    command = "c";
                                    await connectionManager.SendCommand(command);
                                    await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);
                                    break;
                                case "z":
                                    command = "z";
                                    await connectionManager.SendCommand(command);
                                    await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);
                                    break;
                                default:
                                    command = "w";
                                    await connectionManager.SendCommand(command);
                                    await _synthesizer.SpeakTextAsync("Changing Navigation to " + recoResult.Text);
                                    break;
                            }
                        }
                    }
                    catch (System.Threading.Tasks.TaskCanceledException)
                    {
                        // Ignore the cancellation exception of the recoOperation.
                        // When recoOperation.Cancel() is called to cancel the asynchronous speech recognition operation
                        // initiated by RecognizeAsync(),  a TaskCanceledException is thrown to signify early exit.
                    }
                    catch (Exception err)
                    {
                        // Handle the speech privacy policy error.
                        const int privacyPolicyHResult = unchecked((int)0x80045509);

                        if (err.HResult == privacyPolicyHResult)
                        {
                            MessageBox.Show("To run this sample, you must first accept the speech privacy policy. To do so, navigate to Settings -> speech on your phone and check 'Enable Speech Recognition Service' ");
                            _recoEnabled = false;
                            //btnContinuousRecognition.Content = "Start speech recognition";
                        }
                        else
                        {
                            txtResult.Text = "Error: " + err.Message;
                        }
                    }
                }
            }
        }
        //hàm này sẽ trả về hướng đi mà chúng ta điều khiển nếu có trong thư viện
        //nếu phát âm câu lệnh đúng, trả về hướng đi tương ứng, nếu không mặc định sẽ là đi thẳng
        private string TryGetNavigation(string reconozedNavigation)
        {
            if (dict.ContainsKey(reconozedNavigation))
                return dict[reconozedNavigation];
            return dict["lead on"];
        }
        private void annut()
        {
            goAhead_btn.Visibility = System.Windows.Visibility.Collapsed;
            goBack_btn.Visibility = System.Windows.Visibility.Collapsed;
            leftBack_btn.Visibility = System.Windows.Visibility.Collapsed;
            rightback_btn.Visibility = System.Windows.Visibility.Collapsed;
            stop_btn.Visibility = System.Windows.Visibility.Collapsed;
            turnLeft_btn.Visibility = System.Windows.Visibility.Collapsed;
            turnRight_btn.Visibility = System.Windows.Visibility.Collapsed;
        }
        private void hiennut()
        {
            goAhead_btn.Visibility = System.Windows.Visibility.Visible;
            goBack_btn.Visibility = System.Windows.Visibility.Visible;
            leftBack_btn.Visibility = System.Windows.Visibility.Visible;
            rightback_btn.Visibility = System.Windows.Visibility.Visible;
            stop_btn.Visibility = System.Windows.Visibility.Visible;
            turnLeft_btn.Visibility = System.Windows.Visibility.Visible;
            turnRight_btn.Visibility = System.Windows.Visibility.Visible;
        }

        private void btnTouch_Click(object sender, RoutedEventArgs e)
        {
            touch = !touch;
            if (touch == true)
            {
                hiennut();
                ImageBrush background = new ImageBrush();
                background.ImageSource = new System.Windows.Media.Imaging.BitmapImage(new Uri(@"/Assets/Narrow/touch.png", UriKind.Relative));
                btnTouch.Background = background;
                needforspeed.Visibility = System.Windows.Visibility.Collapsed;
                BodyDetectionStatus.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                ImageBrush background = new ImageBrush();
                background.ImageSource = new System.Windows.Media.Imaging.BitmapImage(new Uri(@"/Assets/Narrow/touch2.png", UriKind.Relative));
                btnTouch.Background = background;
                annut();
                needforspeed.Visibility = System.Windows.Visibility.Visible;
                BodyDetectionStatus.Visibility = System.Windows.Visibility.Collapsed;
            }
        }
        //đoạn code tự chế
        
    }
}